package com.example.demo.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCommands;

import java.util.Arrays;
import java.util.Collections;

/**
 * @Author: HouZeYu
 * @Description:
 * @Date: Created in 14:30 2019/8/9
 */
@Component
public class RedisLuaUtils {
    @Autowired
    private RedisTemplate redisTemplate;


    private static final Long SUCCESS=1L;

    private static final Long EXECUTE_SUCCESS =1L ;
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    private static final String LOCK_SUCCESS = "OK";
    private static final String UNLOCK_LUA =
                    "local key=KEYS[1]" +
                    "local value=ARGV[2]" +
                    "if redis.call(\"GET\",key)==value then" +
                            " return redis.call(\"DEL\",key)" +
                            "else" +
                            "return 0" +
                            "end";

    private static final String CACHE_INIT_LUA=
                    " local stock=KEYS[1]" +
                    "local stock_lock=KEYS[2]" +
                    "local stock_val=tonumber(ARGV[1])" +
                    "local stock_lock_val=tonumber(ARGV[2])" +
                    "local is_exist = redis.call(\"EXISTS\",stock)" +
                    "if is_exist==1  then" +
                     "     return  0  " +
                    "else  " +
                         "redis.call(\"SET\",stock,stock_val)" +
                         "redis.call(\"SET\",stock_lock,stock_lock_val)" +
                    "     return 1  " +
                    "end";
    //利用lua脚本执行redis
     public boolean setLua(String stock,String stock_lock,String stock_val,String stock_lock_val){
         Object result= redisTemplate.execute((RedisCallback<Object>) redisConnection -> {
            Jedis jedis = (Jedis) redisConnection.getNativeConnection();
            return jedis.eval(CACHE_INIT_LUA,Collections.unmodifiableList(Arrays.asList(stock,stock_lock)),Collections.unmodifiableList(Arrays.asList(stock_val,stock_lock_val)));
        });
         if (SUCCESS.equals(result)){
            return true;
         }
         return false;
    }
    //设置分布式锁
    public boolean  setnx(String key,String value,long timeout){
        Object result = redisTemplate.execute((RedisCallback<String>) redisConnection -> {
            JedisCommands  jedis = (JedisCommands ) redisConnection.getNativeConnection();
            return jedis.set(key,value,"NX","PX",timeout);
        });
      if ("OK".equals(result)){
          return true;
      }
      return false;
    }
   //释放分布式锁
    public boolean unlock(String key,String value){
        Object result = redisTemplate.execute((RedisCallback<Object>) redisConnection -> {
            Jedis jedis = (Jedis) redisConnection.getNativeConnection();
            return   jedis.eval(UNLOCK_LUA,Collections.unmodifiableList(Arrays.asList(key)),Collections.unmodifiableList(Arrays.asList(value)));
        });
         if (SUCCESS.equals(result)){
             return true;
         }
        return false;
    }
}
